﻿using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Xml;

namespace Avaxo.DlrPad
{
    public class XamlTextBox : TextBox
    {
        #region Properties

        public static readonly DependencyProperty IsXamlValidProperty =
            DependencyProperty.Register( "IsXamlValid", typeof ( bool ), typeof ( XamlTextBox ),
                                         new FrameworkPropertyMetadata( default( bool ) ) );

        public bool IsXamlValid
        {
            get { return (bool) GetValue( IsXamlValidProperty ); }
            set { SetValue( IsXamlValidProperty, value ); }
        }

        #endregion

        #region Events

        public delegate void XamlParsedEventHandler( object sender, XamlParsedEventArgs args );

        public static readonly RoutedEvent XamlParsedEvent =
            EventManager.RegisterRoutedEvent( "XamlParsed", RoutingStrategy.Bubble, typeof ( XamlParsedEventHandler ),
                                              typeof ( XamlTextBox ) );

        public event XamlParsedEventHandler XamlParsed
        {
            add { AddHandler( XamlParsedEvent, value ); }
            remove { RemoveHandler( XamlParsedEvent, value ); }
        }

        protected virtual void OnXamlParsed( XamlParsedEventArgs args )
        {
            RaiseEvent( args );
        }

        public delegate void XamlParseErrorEventHandler( object sender, ErrorEventArgs args );

        public static readonly RoutedEvent XamlParseErrorEvent =
            EventManager.RegisterRoutedEvent( "XamlParseError", RoutingStrategy.Bubble,
                                              typeof ( XamlParseErrorEventHandler ), typeof ( XamlTextBox ) );

        public event XamlParseErrorEventHandler XamlParseError
        {
            add { AddHandler( XamlParseErrorEvent, value ); }
            remove { RemoveHandler( XamlParseErrorEvent, value ); }
        }

        protected virtual void OnXamlParseError( ErrorEventArgs args )
        {
            RaiseEvent( args );
        }

        #endregion

        public XamlTextBox()
        {
            Style = FindResource( typeof ( XamlTextBox ) ) as Style;
        }

        protected override void OnTextChanged( TextChangedEventArgs e )
        {
            base.OnTextChanged( e );

            XmlReader reader = null;
            try
            {
                reader = XmlReader.Create( new StringReader( Text ) );
                object root = XamlReader.Load( reader );
                if ( root != null )
                {
                    OnXamlParsed( new XamlParsedEventArgs( XamlParsedEvent, root ) );
                }

                IsXamlValid = true;
            }
            catch ( Exception ex )
            {
                IsXamlValid = false;
                OnXamlParseError( new ErrorEventArgs( XamlParseErrorEvent, ex ) );
            }
            finally
            {
                if ( reader != null )
                {
                    ( (IDisposable) reader ).Dispose();
                }
            }
        }
    }
}